<!--
 * @Author: fcli
 * @Date: 2023-09-04 10:32:44
 * @LastEditors: fcli
 * @LastEditTime: 2023-11-22 14:47:56
 * @FilePath: /arcgis-demo/src/App.vue
 * @Description: 
-->

<template>
  <div class="wrap">
    <div id="viewDiv" class="map">
      <div id="line-button" class="esri-widget esri-widget--button esri-interactive" title="画线">
        <span class="esri-icon-polyline"></span>
      </div>
      <div id="area-button" class="esri-widget esri-widget--button esri-interactive" title="画面">
        <span class="esri-icon-polygon"></span>
      </div>
      <div id="point-button" class="esri-widget esri-widget--button esri-interactive" title="画点">
        <span class="esri-icon-radio-checked"></span>
      </div>
      <div id="circle-button" class="esri-widget esri-widget--button esri-interactive" title="画圆">
        <span class="esri-icon-radio-unchecked"></span>
      </div>
      <div id="rectangle-button" class="esri-widget esri-widget--button esri-interactive" title="画矩形">
        <span class="esri-icon-checkbox-unchecked"></span>
      </div>
    </div>
    <div class="popup-content" v-for="(item, index) in popupData" :key="index"
      :style="{ top: item.y - 24 + 'px', left: item.x - 30 + 'px' }">自定义弹出层</div>
  </div>
</template>

<script setup lang="ts">
import Map from '@arcgis/core/Map';
import MapView from '@arcgis/core/views/MapView';
import TileLayer from '@arcgis/core/layers/TileLayer';
import Point from '@arcgis/core/geometry/Point';
import Circle from '@arcgis/core/geometry/Circle';
import Polygon from '@arcgis/core/geometry/Polygon.js';
import Polyline from '@arcgis/core/geometry/Polyline.js';
import Draw from '@arcgis/core/views/draw/Draw';
import Graphic from '@arcgis/core/Graphic';
import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
import HeatmapRenderer from '@arcgis/core/renderers/HeatmapRenderer.js';
import { pointList } from './point.ts';
import Field from '@arcgis/core/layers/support/Field';
import '@arcgis/core/assets/esri/themes/dark/main.css';
import { ref, onMounted } from 'vue';
const mapLayers = ref<any>(null);
let pointGraphics:any = [];
const popupData = ref<any>([]);
let myMapView:any = null;
let myMap:any =null;
onMounted(() => {
  initMap();

})
const initMap = () => {
  let map = new Map();
  const view: any = new MapView({
    container: 'viewDiv',
    map: map,
    zoom: 4
  });

  myMap = map;

  view.on('resize', () => {
    renderPopup();
  });

  view.on('drag', () => {
    renderPopup();
  });
  //滚轮事件
  view.on('mouse-wheel', () => {
    setTimeout(() => {
      renderPopup();
    }, 200);
  });

  myMapView = view;


  // 设置弹窗样式
  view.popup = {
    collapseEnabled: false, // 移除title点击折叠功能
    dockOptions: {
      buttonEnabled: false // 隐藏固定标签页
    },
    viewModel: {
      includeDefaultActions: false // 清空事件按钮 （缩放至、...）
      // actions: [] // 清空事件按钮 （缩放至、...）
    }
  };
  // 删除底部powered by ESRI
  view.ui.remove('attribution');
  view.ui.add('line-button', 'top-left'); //添加绘制线按钮，自定义UI
  view.ui.add('area-button', 'top-left'); //添加绘制面按钮，自定义UI
  view.ui.add('point-button', 'top-left'); //添加绘制面按钮，自定义UI
  view.ui.add('circle-button', 'top-left'); //添加绘制面按钮，自定义UI
  view.ui.add('rectangle-button', 'top-left'); //添加绘制面按钮，自定义UI
  view.when(() => {
    let pt = new Point({
      x: -3385.861498285485,
      y: -4869.908083566152,
      spatialReference: view.spatialReference
    });
    // 定位到中心点
    view.goTo({
      center: pt,
      zoom: 2
    });

    //热力图
    rendHeatmap();
    // 点上图
    view.graphics.addMany(renderPoint());
    //多边形面
    view.graphics.addMany(rendPolygon());
    //多边形折线
    view.graphics.addMany(rendPolyline());

    //自定义绘制点、线、面
    const draw = new Draw({
      view: view
    });
    //绑定线按钮绘制事件
    const drawLineButton: any = document.getElementById('line-button');
    drawLineButton.onclick = function () {
      view.graphics.removeAll(); //清楚之前的绘制
      enableCreateLine(draw, view);
    };
    //绑定面按钮绘制事件
    const drawAreaButton: any = document.getElementById('area-button');
    drawAreaButton.onclick = function () {
      view.graphics.removeAll(); //清楚之前的绘制
      enableCreateArea(draw, view);
    };
    //绑定面按钮绘制事件
    const drawPointButton: any = document.getElementById('point-button');
    drawPointButton.onclick = function () {
      enableCreatePoint(draw, view);
    };
    //绑定面按钮绘制事件
    const drawCircleButton: any = document.getElementById('circle-button');
    drawCircleButton.onclick = function () {
      enableCreateCircle(draw, view);
    };
    //绑定面按钮绘制事件
    const drawRectangleButton: any = document.getElementById('rectangle-button');
    drawRectangleButton.onclick = function () {
      enableCreateRectangle(draw, view);
    };

  }).catch(function (err: any) {
    console.error('myMapView rejected:', err);
  });
  //基础图层
  let layerUrl = 'http://xxx.xxx.xxx.xxx/arcgis/rest/services/BaseMap/MapServer'; //地图服务URL
  let layer = new TileLayer({ url: layerUrl, title: 'baseMap' });
  mapLayers.value = layer;
  map.layers.add(layer);
}

//开始监听画线
const enableCreateLine = (draw: any, view: any) => {
  var action = draw.create('polyline', {
    mode: 'click'
  });
  // 获取焦点
  view.focus();

  // 顶点添加事件
  action.on('vertex-add', createPolyline);

  //顶点移除事件
  action.on('vertex-remove', createPolyline);

  // 鼠标移动事件
  action.on('cursor-update', createPolyline);

  // 绘制完成事件
  action.on('draw-complete', createPolyline);
}
//开始监听画面
const enableCreateArea = (draw: any, view: any) => {
  var action = draw.create('polygon', {
    mode: 'click' //点击方式加点
  });
  // 获取焦点
  view.focus();

  // 顶点添加事件
  action.on('vertex-add', createPolygon);

  //顶点移除事件
  action.on('vertex-remove', createPolygon);

  // 鼠标移动事件
  action.on('cursor-update', createPolygon);

  // 绘制完成事件
  action.on('draw-complete', createPolygon);
}
//开始监听画点
const enableCreatePoint = (draw: any, view: any) => {
  var action = draw.create('point', {
    mode: 'click' //点击方式加点
  });
  // 获取焦点
  view.focus();

  // vertex-add 顶点添加事件 vertex-remove 顶点移除事件 draw-complete 绘制完成事件
  action.on(['vertex-add', 'vertex-remove', 'draw-complete'], createPoint);
}
//开始监听画圆
const enableCreateCircle = (draw: any, view: any) => {
  var action = draw.create('circle', {
    mode: 'click' //点击方式加点
  });
  // 获取焦点
  view.focus();
  //顶点移除事件
  action.on('vertex-remove', createCircle);
  // 鼠标移动事件
  action.on('cursor-update', createCircle);
  // 绘制完成事件
  action.on('draw-complete', createCircle);
}
//开始监听画矩形
const enableCreateRectangle = (draw: any, view: any) => {
  var action = draw.create('rectangle', {
    mode: 'click' //点击方式加点
  });
  // 获取焦点
  view.focus();

  //顶点移除事件
  action.on('vertex-remove', createRectangle);
  // 鼠标移动事件
  action.on('cursor-update', createRectangle);
  // 绘制完成事件
  action.on('draw-complete', createRectangle);
}
//根据点坐标生成新的线
const createPolyline = (event: any) => {
  //获取所有顶点
  var vertices = event.vertices;
  //清除之前绘制
  myMapView.graphics.removeAll();
  // 生成绘制的图形
  var graphic = new Graphic({
    geometry: new Polyline({
      paths: vertices,
      spatialReference: myMapView.spatialReference
    }),
    symbol: {
      type: 'simple-line', // autocasts as new SimpleFillSymbol
      color: [4, 90, 141],
      width: 4,
      cap: 'round',
      join: 'round'
    }
  });
  // 将绘制的图形添加到view
  myMapView.graphics.add(graphic);
}
//根据点坐标生成新的线
const createPolygon = (event: any) => {
  //获取所有顶点
  var vertices = event.vertices;
  //清除之前绘制
  myMapView.graphics.removeAll();

  // 生成绘制的图形
  var graphic = new Graphic({
    geometry: new Polygon({
      hasZ: false,
      hasM: false,
      rings: [vertices],
      spatialReference: myMapView.spatialReference
    }),
    symbol: {
      type: 'simple-fill', // autocasts as new SimpleFillSymbol()
      color: [51, 51, 204, 0.9],
      style: 'solid',
      outline: {
        // autocasts as new SimpleLineSymbol()
        color: 'white',
        width: 1
      }
    }
  });
  // 将绘制的图形添加到view
  myMapView.graphics.add(graphic);
}

//根据点坐标生成新的点
const createPoint = (event: any) => {
  //获取所有顶点
  var coordinates = event.coordinates;

  //生成绘制的图形
  var graphic = new Graphic({
    geometry: new Point({
      hasZ: false,
      hasM: false,
      x: coordinates[0],
      y: coordinates[1],
      spatialReference: myMapView.spatialReference
    }),
    symbol: {
      type: 'simple-marker', // autocasts as new SimpleMarkerSymbol()
      style: 'square',
      color: 'blue',
      size: '8px', // pixels
      outline: {
        // autocasts as new SimpleLineSymbol()
        color: [255, 255, 0],
        width: 3 // points
      }
    }
  });
  // 将绘制的图形添加到view
  myMapView.graphics.add(graphic);
}
//根据点坐标生成新的线
const createCircle = (event: any) => {
  //获取所有顶点
  var vertices = event.vertices;
  //少于一个点无法展示圆
  if (vertices.length < 2) {
    return;
  }
  //清除之前绘制
  myMapView.graphics.removeAll();
  //生成绘制的图形,两点画圆
  var center = new Point({
    hasZ: false,
    hasM: false,
    x: vertices[0][0],
    y: vertices[0][1],
    spatialReference: myMapView.spatialReference
  });
  var dis = center.distance(
    new Point({
      hasZ: false,
      hasM: false,
      x: vertices[1][0],
      y: vertices[1][1],
      spatialReference: myMapView.spatialReference
    })
  );
  var graphic = new Graphic({
    geometry: new Circle({
      hasZ: false,
      hasM: false,
      center: center,
      radius: dis,
      spatialReference: myMapView.spatialReference
    }),
    symbol: {
      type: 'simple-fill', // autocasts as new SimpleFillSymbol()
      color: [51, 51, 204, 0.9],
      style: 'solid',
      outline: {
        // autocasts as new SimpleLineSymbol()
        color: 'white',
        width: 1
      }
    }
  });
  // 将绘制的图形添加到view
  myMapView.graphics.add(graphic);
}
const createRectangle = (event: any) => {
  //获取所有顶点
  var vertices = event.vertices;

  //两点画矩形
  if (vertices.length < 2) {
    return;
  }
  var rings = [vertices[0], [vertices[0][0], vertices[1][1]], vertices[1], [vertices[1][0], vertices[0][1]]];
  //清除之前绘制
  myMapView.graphics.removeAll();

  // 生成绘制的图形
  var graphic = new Graphic({
    geometry: new Polygon({
      hasZ: false,
      hasM: false,
      rings: [rings],
      spatialReference: myMapView.spatialReference
    }),
    symbol: {
      type: 'simple-fill', // autocasts as new SimpleFillSymbol()
      color: [51, 51, 204, 0.9],
      style: 'solid',
      outline: {
        // autocasts as new SimpleLineSymbol()
        color: 'white',
        width: 1
      }
    }
  });
  // 将绘制的图形添加到view
  myMapView.graphics.add(graphic);
}

//热力图
const rendHeatmap = () => {
  //热力图渲染
  var heatmapRenderer = new HeatmapRenderer({
    //设置渲染器
    field: 'count', //设置的权重字段
    colorStops: [
      { color: 'rgba(0, 255, 150, 0)', ratio: 0 },
      { color: '#32C5E9', ratio: 0.083 },
      { color: '#67E0E3', ratio: 0.166 },
      { color: '#9FE6B8', ratio: 0.249 },
      { color: '#FFDB5C', ratio: 0.332 },
      { color: '#ff9f7f', ratio: 0.415 },
      { color: '#fb7293', ratio: 0.498 },
      { color: '#E062AE', ratio: 0.581 },
      { color: '#E690D1', ratio: 0.664 },
      { color: '#e7bcf3', ratio: 0.747 },
      { color: '#9d96f5', ratio: 0.83 },
      { color: '#8378EA', ratio: 0.913 },
      { color: '#96BFFF', ratio: 1 }
    ],
    radius: 10,
    maxDensity: 0.01625,
    minDensity: 0
  });
  let features: any = [];
  pointList.forEach((item: any, index: number) => {
    features.push({
      geometry: {
        type: 'point',
        x: item.COORDX,
        y: item.COORDY,
        spatialReference: myMapView.spatialReference
      },
      attributes: {
        count: 1,
        ObjectID: index //重要！！！
      }
    });
  });
  const hfields = [
    new Field({
      name: 'count',
      alias: 'count',
      type: 'string'
    })
  ];
  var featureLayer = new FeatureLayer({
    id: '热力图',
    source: features, //点数据集
    title: '热力图',
    objectIdField: 'ObjectID',
    fields: hfields, //权重字段
    renderer: heatmapRenderer
  });
  myMap.add(featureLayer);
}

//撒点
const renderPoint = () => {
  let pointGraphicArr: any = [];
  pointList.forEach((item: any) => {
    // First create a point geometry
    let point = {
      type: 'point', // autocasts as new Point()
      longitude: item.COORDX,
      latitude: item.COORDY,
      spatialReference: myMapView.spatialReference
    };


    //点样式,(可设置图片，或者自定义颜色的marker，参考symbol)
    let markerSymbol = {
      // type: 'picture-marker',
      // url: img,
      // width: 5,
      // height: 5
      type: 'simple-marker',
      color: [226, 119, 40]
    };

    // 创建点的属性
    let attributes = {
      Name: item.ADDRESS,
      Owner: item.TASKID
    };

    // Create a graphic and add the geometry and symbol to it
    let pointGraphic = new Graphic({
      geometry: point,
      symbol: markerSymbol,
      attributes: attributes
    });

    pointGraphicArr.push(pointGraphic);
  });
  pointGraphics = pointGraphicArr;

  //自定义渲染popup
  setTimeout(() => {
    renderPopup();
  }, 500);

  return pointGraphics;
}

//自定义渲染popup
const renderPopup = () => {
  let popupDataArr: any = [];
  pointGraphics.forEach((item: any) => {
    let screen = myMapView.toScreen(item.geometry);
    popupDataArr.push(screen);
  });
  popupData.value = popupDataArr;
}
//绘制多边形覆盖层面
const rendPolygon = () => {
  const rings = [
    [-4226.57763671875, -10710.984375],
    [-5061.92724609375, -8761.8974609375],
    [-5428.50244140625, -10374.7802734375]
  ];

  const polygon = {
    //面的坐标信息
    type: 'polygon',
    rings: rings,
    spatialReference: myMapView.spatialReference
  };
  const fillSymbol = {
    //面的样式
    type: 'simple-fill',
    color: [227, 139, 79, 0.8],
    outline: {
      // autocasts as new SimpleLineSymbol()
      color: [255, 255, 255],
      width: 1
    }
  };
  const polygonGraphic = new Graphic({
    //创建面图斑
    geometry: polygon,
    symbol: fillSymbol
  });
  //数组
  return [polygonGraphic];
}

//多边形折线
const rendPolyline = () => {
  const polyline = {
    //线的坐标信息
    type: 'polyline', // autocasts as new Polyline()
    paths: [
      [-4466.80859375, -8273.7109375],
      [-3475.872802734375, -6549.30810546875],
      [-4307.0634765625, -5647.63525390625],
      [-4466.80859375, -8273.7109375]
    ],
    spatialReference: myMapView.spatialReference
  };
  const lineSymbol = {
    //线的样式
    type: 'simple-line',
    color: [226, 119, 40],
    width: 2
  };
  const lineAtt = {
    //线的属性
    Name: 'Keystone Pipeline',
    Owner: 'TransCanada',
    Length: '3,456 km'
  };
  const polylineGraphic = new Graphic({
    //创建线对象并且绑定属性以及弹出框信息
    geometry: polyline,
    symbol: lineSymbol,
    attributes: lineAtt
  });

  return [polylineGraphic];
}
</script>

<style>
.popup-content {
    position: absolute;
    font-size: 10px;
    background: #fff;
    padding: 0 8px;
    border-radius: 8px;
}

.wrap,
#viewDiv {
    position: relative;
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
}
</style>
